/************************************************************************************************************************************************
 *   Copyright (C) 2008 by Denjs                                                                                                                *
 *   dplsoft@pisem.net                                                                                                                          *
 *   http://qdroid.berlios.de                                                                                                                   *
 * -----------------------------------------------------------------------                                                                      *
 *   This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or (at your option) any later version.                                      *
 *   This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.                                 *
 *   You should have received a copy of the GNU General Public License along with this program; if not, write to the                            *
 *   Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                                                  *
 * -------------------------------------------------------------------------------------------------------------------------------------------- *
 *     Эта программа является свободным программным обеспечением; вы можете распространять её и/или модифицировать в соответствии с лицензией   *
 *   GNU General Public License  (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU) версии 2.0 или более поздней - на ваш выбор.                         *
 *     Эта программа распространяется  в надежде что она будет вам полезна, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, подразумеваемых или явных; без обещаний *
 *   полезности или применимости в конкретных условиях. Вы используете  данное ПО на свой страх и риск и сами полностью несете                  *
 *   ответственность за последствия. См. GNU General Public License (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU).                                  *
 *     Вы должны получить копию GNU General Public License (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU)с данным ПО; Если этого не случилось,       *
 *   обратитесь в Фонд Свободного Программного Обеспечения :                                                                                    *
 *   Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                                                  *
 * -------------------------------------------------------------------------------------------------------------------------------------------  *
 * Замечания для территории России: в соответствии с ГК РФ часть 4, начиная использовать данную программу (исполняемые файлы или исходные       *
 * тексты) вы автоматически соглашаетесь с данной лицензией.
 ************************************************************************************************************************************************/

#include "t_QDroid.h"

/* ==================================================================
*/
t_QDroid::t_QDroid(QObject *parent)
    : QObject(parent)
{
 	DebugLevel=0;
 	//	
//	DroidGui	= new t_DroidGui(NULL);
//	ObjectReg	= new t_ObjectRegistry(this);//репозитарий объектов (внешних поставщиков объектов)/ будет описан позже всего.
	//FunctionReg	= new t_FunctionRegistry(this);//репозитарий подключенных функций
	
	QSEngine	= new QScriptEngine();
        hiveDebugger    = new QScriptEngineDebugger();
        //isDebuggerAttched = false;
        _useDebugger = false;
	FunctionRegItem = new t_FunctionRegistryItem();//новый создадим
	BaseBot		= new t_BaseBot(FunctionRegItem, this); // "первый слуга", базовый бот доступный в скриптовой среде.
		
					// выполняет общие функции типа "кто тут", списко операций и т.п.
					// предположительно - интерфейс для общения с HiveQueen - по загрузке и выгрузке элементов...
					// и управления системой из скриптов.
	QDLibManager = new t_QDLibManager(QSEngine, this); 	// менеджер расширений qDROID
        doQuitOnErrors=true;//++2010.06.09
        inited=false;
	//2008.12.25 - процесс сборки системы перенесен в init()

        scriptEngineAgent = new t_QDroid_QScriptEngineAgent(QSEngine);
}

//-------------------------------------------------------------------------------------------
bool t_QDroid::set_doQuitOnErrors(bool newVar)
    {   bool oldVar;
        doQuitOnErrors=newVar;
        return oldVar;
    };
//-------------------------------------------------------------------------------------------
// ++2010.05.24
QScriptEngine * t_QDroid::getQScriptEngine()
{
    return this->QSEngine;
}

//-------------------------------------------------------------------------------------------
int t_QDroid::script_list_item_activated ( const QModelIndex & index ) //не гут наверное это здесь вешать но пока ладно. 2008.12.05
{
/*
	//qDebug()<<"t_QDroid::script_list_item_activated ()::[0080] "<<index.row();
	connect_to_regitem(index.row());
    ScriptDescriptionObject->setText("Name:\n    "+ FunctionRegItem->Name+" \nDescription:\n    "+FunctionRegItem->Description+"\nSource File:\n    "+ FunctionRegItem->FileName+"");
*/
}
int t_QDroid::script_list_item_clicked( const QModelIndex & index ) //не гут наверное это здесь вешать но пока ладно. 2008.12.05
{
}

int t_QDroid::script_list_item_doubleClicked( const QModelIndex & index ) //не гут наверное это здесь вешать но пока ладно. 2008.12.05
{
}

/* ==================================================================
*/
t_QDroid::~t_QDroid()
{

}

//
/* ==================================================================
++2010.05.21_2200
*/
/*/
QScriptEngine * t_QDroid::getScriptEngine();
    {
        return QSEngine;
    }
//*/
/* ==================================================================
    ++2010.05.21_2200
*/
int t_QDroid::init()
{
    init(argList);
}
/* ==================================================================
 инициация и запуск системы. Отсюда все начинается.
 !: причем только в случае работы как интерпритатора из команной строки.
 вариант запуска произвольного куска кода в каком-либо контексте - здесь не рассматривается...
 НО! первый раз должны запуститься через эту процедуру.
 скажем так - проинициировать среду что ли ?

 // QStringList argList - параметры для самой среды. возможно с именем файла.
*/
//int t_QDroid::init(QStringList argList)
int t_QDroid::init(QStringList argList, QObject * _context)
{
    bool firstTime=false;

    if (!inited)
       {
         inited=true;
         firstTime=true;
         /*
           { //пробник 2011.03.18
             //продуем сделать финт ушами - пересоздать скриптовое ядро что бы оно уничтожило все старые объекты относящиеся к скрипту.
             // не красиво но пока похоже нет штатного механизма принудительно выгрузить "исполняющийся" скрипт
             // вернее его остатки, которые остались в памяти и в принципе правильно функционируют и обрабатывают сигналы.
             inited=false;
             QSEngine->deleteLater();
             QSEngine = new QScriptEngine(this);
             scriptEngineAgent = new t_QDroid_QScriptEngineAgent(QSEngine);
             ScriptSource=QStringList();
             //init(QStringList(),_context); // тут повялятся ошибки, мол нет скрипта и прочее.. пока игнорируем
             //ScriptSource = _ScriptSource;

         }/*-*/
       };

    //setScriptObjectVar(QString("_context"),_context);//
    if (hiveDebugger!=0)
        {
            hiveDebugger->detach();
            hiveDebugger->deleteLater();
        };
    set_useDebugger(false);

    hiveDebugger    = new QScriptEngineDebugger();

    if (firstTime)
      {
        BaseBot->useGui = this->useGui();
        BaseBot->platformVersion = this->platformVersion();
	QString ScriptRegFile;
	//базового бота - сразу засунуть в среду скрипта
	QScriptValue ScriptObjectValue1 = QSEngine->newQObject(BaseBot);
	QSEngine->globalObject().setProperty("BBot", ScriptObjectValue1);
	QScriptValue ScriptObjectValue2 = QSEngine->newQObject(&stdReader);
	QSEngine->globalObject().setProperty("StdStreamsGate", ScriptObjectValue2);
	//:: [[@stdstreamsgate]] [[:qdroid_stdobject]]
	//::====StdStreamsGate====
	//::Объект класса [[stdinreader]]. \n Предоставляет доступ к потокам ввода/вывода для обмена данными с внешней(родительской) средой.
	
	connect(QSEngine,SIGNAL(signalHandlerException(const QScriptValue &)),this,SLOT(signalHandlerException_rcv( const QScriptValue &)));

	//переопределим print() на std_out для BaseBot
	//определим ряд дополнительных функций доступных в QTScript
	define__qdroid_qtscript_functions(QSEngine,BaseBot,QDLibManager);

	//привяжем StdOut от BaseBot к "ЦНС" HiveQueen
	connect(BaseBot,SIGNAL(std_out(QString)),this,SLOT(std_out_resend(QString)));

    };//if (firstTime)

//--------------
	//получим имя файла для целей фильтрации параметров из-командной строки
	QString thisPathName=QCoreApplication::applicationDirPath();
	QString thisFileName=(QCoreApplication::applicationFilePath()).remove(0,thisPathName.size()+1);
		
	int startPos=0;
       if (argList.size()>0)
        if ((argList.at(0).endsWith(thisFileName)) //на тот случай если запускаемся по относитльному пути
	  or (argList.at(0).endsWith("qdroid")) // да. даже так. пока именно так. глупо, да. Под linux это стандартная ссылка на наш файл.
//	  or (argList.at(0)=="qdroid") // да. даже так. пока именно так. глупо, да.
	   )
		startPos++;//если словили cвое имя файла - то его надо пропустить
		/*
		весь косяк в том, что когда мы под windows стартуем как дочерний процесс
		 - в некоторых случаях нам могут не дать наше имя в качестве 
		нулевого параметра... из-за этого этот кусок кода и появился.
		На самом деле надо проверить, возможно QCoreApplication::arguments() 
		и исправляет данную ситацию, но пока будем думать что нет.
		по крайней мере чтение аргументов из *argv[] в main() приводит 
		именно к обнаружению такой ситуации.
		*/
	/*
	   разбор argList
	*/
//--------------
	startPos=1;//НО пока требуем чтобы в начале всегода шло имя файла, а аргументы начинались со второго по порядку

	QString currentParam;
	QString scriptFileName;
	QStringList scriptArgList;
	int state=0;//state of option recognition machine
	int activeParam=0;//количество активных/полезных параметров 
	qDebug() <<" arg list size::"<<argList.size();
	for (int q=startPos;q<argList.size();q++)
	  {
		currentParam=argList.at(q);
                if (currentParam.trimmed().isEmpty()) continue;// пустые опии не надо даже смотреть)))
		qDebug() <<" arg::"<<q<<" = ["<< currentParam <<"]";

                if (
                        (currentParam.startsWith("-")) //значит опция а не им файла файл // собственно это нам нужно на тот случай, если мы ошиблись в опции. НО! индикация об ошибочной опции пока не введена
                     and (state==0)
                    )
                  {
                        if (
                              (state==0)
                              and ((currentParam==QString("-c"))
                                or (currentParam==QString("--config"))
                              )
                           ) // not emplemented yet: use cpecial config file
                                  {
                                        qDebug() <<" ^^^^^^^^^^^^^ looks like a CONFIG option";
                                        qDebug() << "WARNING:: {-c|--config} config file option does not supported yet";
                                        state=1;//waiting for config file name
                                        continue;
                                  };

                        //++2010.06.28
                        //запустить в дебаггере
                        if ((state==0)
                          and ((currentParam==QString("-d"))
                              or (currentParam==QString("--debug"))
                              )
                           )
                                  {
                                        hiveDebugger->attachTo(this->QSEngine);
                                        set_useDebugger(true);
                                        //if (isDebuggerAttched==false)
                                        //    {
                                        //        isDebuggerAttched=true;
                                        //    };
                                                //// hiveDebugger->action(QScriptEngineDebugger::InterruptAction)->trigger(); //при начале выплнения - надо появиться.
                                                //QMainWindow *debugWindow = hiveDebugger->standardWindow();
                                                //debugWindow->resize(1024, 640);
                                              hiveDebugger->standardWindow()->resize(1024, 640);
                                              hiveDebugger->setAutoShowStandardWindow(true);


                                        qDebug() <<" ^^^^^^^^^^^^^ looks like a DEBUG option";
                                        //qDebug() << "WARNING:: {-c|--config} config file option does not supported yet";
                                        state=0;//waiting for config file name
                                        continue;
                                  };

                        if (
                                (state==0)
                                and
                                (
                                  (currentParam==QString("--help"))
                                  or (currentParam==QString("-h"))
                                  or (currentParam==QString("--usage"))
                                )
                           )
                                  {
                                        qDebug() <<" ^^^^^^^^^^^^^ looks like a HELP request";
                                        std_out_resend_HTML( QString("\nUsage help:\n qdroid [-h|--help|--usage] \n qdroid [{-c|--config} configFileName] [-d|--debug] scriptFileName.qs [scriptOptions] "));
                                        if (doQuitOnErrors) QApplication::quit();
                                        return -1;
                                  };

                    } //currentParam.startsWith("-")
                else
                    {
                            if (state==1)//waiting for config file name
                              {
                                    //qDebug() << "WARNING:: {-c|--config} config file option does not supported yet";
                                    qDebug() <<" ^^^^^^^^^^^^^ looks like a CONFIG file name";
                                    state=0;//waiting for config file name
                                    //configFileName=currentParam;
                                    continue;
                              };


                            if (state==10) //идет набор параметров скрипту
                              {
                                    scriptArgList.append(currentParam);
                                    qDebug() <<" ^^^^^^^^^^^^^ looks like a script argument";
                                    continue;
                              };

                            if (state==0)
                              {
                                    state=10;// waiting for arguments for script
                                    qDebug() <<" ^^^^^^^^^^^^^ looks like a script FileName";
                                    scriptFileName=currentParam;//Если состояние нулевое - то думаем что имя скрипта для исполнения.
                                    activeParam++;
                                    continue;
                              };

                    };//else //currentParam.startsWith("-")
		
	  };
	this->BaseBot->arguments=scriptArgList;//not good! not signalslot!
	if (activeParam<1)
	  {
		std_out_resend_HTML( QString("\n:-0138 ERR No Script File Given. Type \"qdroid --usage\" to get usage help."));
                if (doQuitOnErrors) QApplication::quit();
		return -1;
	  };
	
//	//if (argList.size()>1) //пока просто так. Если что-то указали в командной строке - значит будет режим "shell"
		WorkProfile=QDroid_WorkProfile_SHELL;
//	//else
//	//	WorkProfile=QDroid_WorkProfile_GUI;
//	/* TODO: добавить сюда работу со встроенным документом shell
//		ввод данных через StdIn ???? */
	
	if (DebugLevel>=4) qDebug()<<"t_QDroid::init:[00110]::Switching to mode ["<< WorkProfile <<"]";
	
	/**/
	// shell-вариант - вывод на поле DroidGui
//	if (WorkProfile==QDroid_WorkProfile_SHELL)
//	  {
        // надо загрузить единственный скрипт и выполнить его.
        // где лежит скрипт - из самого аргумента - он нам передается с полным путем.
        if (DebugLevel>=4) qDebug()<<"t_QDroid::init:[00192] <CP reached>";
        //TMP: загрузим скрипт

        if (loadNewScript(scriptFileName)!=0)//<0? были ошибки.
              {
                //std_out_resend_HTML( QString("\n:-0227 ERR Error loading Script File Given. Cheсk if file is exist."));
                qDebug()<< QString("ERROR::-0227 ERR Error loading Script File Given. Cheсk if file is exist.");
                if (doQuitOnErrors) QApplication::quit();
                return -2;
              };
        //получим абсолютный путь вне зависимости от того относительный или абсолютный путь задан на входе
        //QDir dir(QApplication::applicationDirPath());
        //QDir dir2(scriptFileName);
        QDir dir;
        QString scriptPathName ="" ;
        //if (QDir::isRelativePath(scriptFileName))
        //    ...
        scriptPathName = dir.absoluteFilePath(scriptFileName);
        qDebug() << "absolute scriptPathName = " << scriptPathName;
        //BaseBot->c_scriptFilePath=scriptPathName;
        if (scriptPathName.endsWith("/")||scriptPathName.endsWith("\\"))
            scriptPathName.chop(1);
        QDir dir2(scriptPathName);
        //if (dir2.exists(scriptPathName))
            {
                BaseBot->c_scriptFileName=dir2.dirName();
                qDebug() << "absolute scriptFileName = " << BaseBot->c_scriptFileName;

                scriptPathName.chop(BaseBot->c_scriptFileName.length());
                BaseBot->c_scriptDirPath=scriptPathName;
                qDebug() << "absolute scriptFileDir = " << BaseBot->c_scriptDirPath;
            };

//	  };
	
	//qDebug()<<"Current path is ["<<QDir::currentPath()<<"]";
	//qDebug()<<"Application path is ["<<QCoreApplication::applicationDirPath()<<"]";


	//***************************************************************************
	//ВСЕ! с этого момента ввод/вывод из sdtin|sdtout подностью отдается в скрипт.
	stdReader.open();
	//stdReader.run(); но запуск чтения - не ранее чем по команде из скрипта
	
	if (DebugLevel>=5) qDebug() << "QDroid::init()[00211]: exit. QDroid starting.";
	// shell-вариант - запустимся)
        QScriptValue retValue;
//	if (WorkProfile==QDroid_WorkProfile_SHELL)
//	  {
                //FunctionRegItem->init_execution();//TO REWRITE!
                //от FunctionRegItem - НАДО ИЗБАВЛЯТЬСЯ!
		//  и вызвать непосредственно script_to_execute() самого себя
                retValue=evaluateScript(ScriptSource, _context);
//	  };

	//std_out_resend("[LOG] t_QDroid::init()::[0058] ");
 
	if (DebugLevel>=5) qDebug() << "QDroid::init()[00211]: exit. QDroid finished.";

	// TODO if (!QSEngine->isEvaluating()) QApplication::quit();// в люблм случае выкидывает.
	//	даже если объекты созданы BUG!

	return 0;
}


/* ==================================================================
  тестовый слот.
*/
//int t_QDroid::init2()
//{
//	//DroidGui->setWindowTitle("init2 resived");
//	return 0;
//}


/* ==================================================================
 слот для сбора stdout-данных от подчиненных.
 пока просто пересылаем далее.

*/
void t_QDroid::std_out_resend(QString Message)
{
//	if (WorkProfile==QDroid_WorkProfile_SHELL)
	  qDebug()<< Message;
//	 else
//	  {
//	 	emit std_out(Message);
//	  };
}

void t_QDroid::std_out_resend_HTML(QString Message)
{
//	if (WorkProfile==QDroid_WorkProfile_SHELL)
	  qDebug()<< Message;
//	 else
//	  {
//	 	emit std_out_HTML(Message);
//	  };
}

/* ==================================================================
	тут ловим скрипт который нас просят исполнить.
 	и собственно отправляем его на обработку.
*/
//was void
//QScriptValue t_QDroid::script_to_execute(QStringList _ScriptSource)
QScriptValue t_QDroid::evaluateScript(QStringList _ScriptSource, QObject *context)
{
    //setScriptObjectVar(QString("_context"),_context);//
    if (_ScriptSource.isEmpty())
        return false;

    //сначала избавимся от старого исполняющего ся сейчас скрипта...
    //хотя abortEvaluation() почему-то не срабатывает
    if (QSEngine->isEvaluating())
        {
            QSEngine->abortEvaluation();
            if (QSEngine->isEvaluating())
                    qDebug()<< "ERROR!? [00448]: script is still working?!";

            //продуем сделать финт ушами - пересоздать скриптовое ядро что бы оно уничтожило все старые объекты относящиеся к скрипту.
            // не красиво но пока похоже нет штатного механизма принудительно выгрузить "исполняющийся" скрипт
            // вернее его остатки, которые остались в памяти и в принципе правильно функционируют и обрабатывают сигналы.
          /*
            { //пробник 2011.03.18
                inited=false;
                QSEngine->deleteLater();
                QSEngine = new QScriptEngine(this);
                scriptEngineAgent = new t_QDroid_QScriptEngineAgent(QSEngine);
                ScriptSource=QStringList();
                init(QStringList(),context); // тут повялятся ошибки, мол нет скрипта и прочее.. пока игнорируем
                ScriptSource = _ScriptSource;

            }/*-*/

            QSEngine->popContext(); //2011.03.17 probes
            scriptContext = NULL;

        };
    QSEngine->collectGarbage();
    QSEngine->clearExceptions();
    //2011.04.04 - нужен отладчик, + видимо надо бдет пересоздавтаь ядро каждый раз...
    //QSEngine->setAgent(scriptEngineAgent);//это кстати приведет к тому, что будет отключен отладчик, если он был подключен.

    //теперь опишем новый контекст
    scriptContext = QSEngine->pushContext();


    QScriptValue ScriptObjectValue_thisForContext = QSEngine->newQObject(context);
    //QSEngine->globalObject().setProperty(QDroid_StandartVar_LocalContext_Name, ScriptObjectValue_local1);
    scriptContext->setThisObject(ScriptObjectValue_thisForContext);
    scriptContext->setActivationObject(ScriptObjectValue_thisForContext);
    scriptContext->activationObject().setProperty(QDroid_StandartVar_LocalContext_Name, ScriptObjectValue_thisForContext);
    //устанавливаем "globalThisObject" - QDroid_StandartVar_LocalContext_Name именно в контексте исполнения.

	QString DBGPlace="t_QDroid::script_to_execute()";
	//int DebugLevel=2;
	//if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00259]::[CheckPoint]";
	
	//emit std_out("[ ] t_QDroid::script_to_execute()::[0099]: Signal Resived");
        QString ScriptInStr="";
	QString Message,StrPart,color,TmpStr;
	QStringList StrList;
            if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00259]::[CheckPoint]";
        ScriptSource=_ScriptSource;
        QStringList ScriptSource_prepocessed=prerpocess_script(ScriptSource);
        StrList= ScriptSource_prepocessed;//сразу пропустим его через препроцессор.
            if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00262]::[CheckPoint]";
	
	int q;
	for (;!StrList.isEmpty();)
		{
			TmpStr=StrList.takeFirst();
			ScriptInStr.append(TmpStr).append(" ");
		};
        if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00261]::[CheckPoint]";
	std_out_resend("Starting to execute script.\n=={START}==================================");

/*TMP TOD */	
        //hiveDebugger->action(QScriptEngineDebugger::InterruptAction)->trigger();
        //остановку в начале скрипта будем делать через вписыванеи debugger в первую строчку скрипта.
        // почему-то если сделать через action()->trigger() при повторном вызове возникает Q_ASSERT(snap != 0); в 414 строке в qscriptdebuggercommandexecutor.cpp
        // строка добавляется в prerpocess_script


        // context->activationObject().setProperty("myArg", 123);
        // engine.evaluate("var tmp = myArg + 42");
        // ...
        // engine.popContext();


        QScriptValue res=QSEngine->evaluate(ScriptInStr);
        //тут подвиснем пока... пока скрипт не отработает до конца...
	if (QSEngine->hasUncaughtException())
	  {
	     int line = QSEngine->uncaughtExceptionLineNumber();
	     std_out_resend( QString("=={ERROR}=================================="));
	     std_out_resend_HTML( QString("Uncaught exception at line %1 : ").arg(line).append(res.toString())+"");
	     Message="";StrList=QSEngine->uncaughtExceptionBacktrace();
	     for (;!StrList.isEmpty();) Message.append(StrList.takeFirst()).append(" ");
	     std_out_resend( QString("Exception BackTrace: ")+ Message +"");

             Message=QString();StrList=ScriptSource_prepocessed;
	     int old=-1;
	     for (q=1;!StrList.isEmpty();q++)
	    	  {	/*
				 StrPart=StrList.takeFirst();
				 if ((q>line-5)&(q<line+5))
				  {
					 if (q!=line) color="green"; else color="red";
					 if (old!=q)
						 Message.append(QString("%1:<font color="+color+">").arg(q)+StrPart+"</font><br>\n");
					 else
						 Message.append(QString("  :")+StrPart+"<br>");
				  };
				 old=q;
				 if (StrPart.endsWith("\\\n")) {q--;};
			*/  // 2009.09.04 изменено под работу только в консоли
				 StrPart=StrList.takeFirst();
				 if ((q>line-5)&(q<line+5))
				  {
					 if (q==line) color="ERR->"; else color="    :";
					 if (old!=q)
						 Message.append(QString("%1:"+color+"").arg(q)+StrPart+"");
					 else
						 Message.append(QString("    :")+StrPart+"");
				  };
				 old=q;
				 if (StrPart.endsWith("\\\n")) {q--;};//<--------- не помню с чем связано, кажется с многострочными строками.заканчиващимися на \n 
					// т.е. для скрипового ядра - это одна строка, 
					// а для файла - несколько...

	    	  };
	     std_out_resend_HTML( QString("Source: \n")+ Message );
	     std_out_resend_HTML( QString("\n:-0323 ERR Uncaught exception at line %1 : ").arg(line).append(res.toString())+"");

	  }
	else
         std_out_resend( QString("=={FIN}=====================================\nCommon result is: ").append(res.toString()) );

     //2011.03.18 REMMED
     //QSEngine->popContext();
     //QSEngine->collectGarbage();

  return res;  //++2010.06.23
}

//==================================================================
/* SLOT
*/
void t_QDroid::signalHandlerException_rcv ( const QScriptValue & exception )
{
	if (QSEngine->hasUncaughtException())
	  {
	    int line = QSEngine->uncaughtExceptionLineNumber();
	    QString Message1 = QString("=={ERROR}==================================");
	    QString Message2 = QString("\n:-0338 ERR Uncaught exception at line %1 : ").arg(line).append(exception.toString());
		std_out_resend(Message1);//std_out_resend for a some time we needs to see  it in debug or
		std_out_resend(Message2);
	  };
}
//===================================================================
/*
        реализация препроцессора. пока тут ничего не делаем. перебор с анализом и узнаванем инструкций,
        потом если функционал будет расширен - надо будет вынести в отдельный класс
*/
QStringList t_QDroid::prerpocess_script(QStringList _ScriptSource)
{

	QString DBGPlace="t_QDroid::prerpocess_script";

    //if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00259]::[CheckPoint]";
	if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00328]::[CheckPoint].Started.";

//	int q;
        bool deguggerStIsSet=false;
	QStringList StrList=_ScriptSource;
	QStringList OutStrList;
	QString TmpStr;
	QChar PreProPrefix='#';//префикс препроцессорной инструкции
	if (DebugLevel>=4) qDebug()<<"DBG.L4::"<<DBGPlace<<":[00334]::[CheckPoint]";


	for (;!StrList.isEmpty();)
	  {
		TmpStr=StrList.takeFirst();
		if (DebugLevel>=4) qDebug()<<"DBG.L5::"<<DBGPlace<<":[00334]::[CheckPoint]";

		if (TmpStr.trimmed().startsWith(PreProPrefix))
		 {  //значит это препроцессорная инструкция.. её надо обработать...
			if (DebugLevel>=5) qDebug()<<"DBG.L5::"<<DBGPlace<<":[00355]:: strdump:"<<TmpStr;
                        TmpStr = QString("//%1").arg(TmpStr);
                        if ((_useDebugger) and (!deguggerStIsSet)) //++2010.06.29 - добавим признак остановки для дебаггера
                            {
                                TmpStr = QString("debugger;%1").arg(TmpStr);
                                deguggerStIsSet=true;
                            };
                        OutStrList.append(TmpStr);//пока просто "закомментим"
			//никаких include "file.iqs" и др. инструкций
		 }
		else
		 {
			if (DebugLevel>=5) qDebug()<<"DBG.L5::"<<DBGPlace<<":[00350]:: strdump:"<<TmpStr;
                        if ((_useDebugger) and (!deguggerStIsSet)) //++2010.06.29 - добавим признак остановки для дебаггера
                            {
                                TmpStr = QString("debugger;%1").arg(TmpStr);
                                deguggerStIsSet=true;
                            };
                        OutStrList.append(TmpStr);
		 };
	  };

   return OutStrList;
}

//======================================================================
//загрузим файл с обработкой кодировок (указание "препроцессора" #codepage
//БЕЗ обрпботки препроцессором. prerpocess_script() будет вызван при начале исполнения - в evaluateScript()
//результат будет помещен в .ScriptSource
//
// перенесено сюда из удаляемго класса t_functionRegistryItem
int t_QDroid::loadNewScript(QString _FileName )
{
        QString DBGPlace="t_QDroid::loadNewScript()";
        QString Msg;
        int DebugLevel=1;//0..5 - от "молчим2 до "подробного" отчета
        QString DirPath;

        //QStringList ScriptSource;

        QString QDroidScriptString="#!/bin/qdroid";
        QString QDroidScriptString2="#!/usr/bin/qdroid";
        QString QDroidCodePageOption="codepage";
        QString CurrentScriptCodePage="";//

        if (_FileName.isEmpty())
          {
            Msg = "No file to load is given.";
            qDebug() << "ERROR:"+DBGPlace+":[00615]"+Msg;
            return -1;
          };
    //TODO! Вставить сюда загрузку из относительного каталога!

    //emit std_out("[checkpoint] t_FunctionRegistryItem::loadNewScript()::[0049]: try to load file: ["+this->FileName+"]");
    QFile file(_FileName);
    ScriptSource.clear();

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
                        QString Msg="[ERROR] Error while loading file ["+_FileName+"]";
                        //emit std_out( "ERROR:"+DBGPlace+":[0075]"+Msg);
                        //if (DebugLevel>=1)
                            qDebug()<<"ERROR:DBG.L1::"<<DBGPlace<<":[00076]::"<<Msg;
                        return -1;
        };

    QDir scriptDir;
    DirPath= scriptDir.cleanPath( scriptDir.absoluteFilePath(_FileName) ) ;
    //DirPath= scriptDir.cleanPath( scriptDir.absolutePath(_FileName) ) ;

    QString Line0=QString().append(file.readLine());
    QString Line1=QString().append(file.readLine());

    //попробуем осознать, что нам подсовывают...
    if (     (Line0.trimmed().toLower()!=QDroidScriptString.toLower())
         and (Line0.trimmed().toLower()!=QDroidScriptString2.toLower())
        )
      {
        QString Msg="[WARNING!] seems it is not QtDroid script.";
        //emit std_out( "WARNING::"+DBGPlace+":[0089]"+Msg);
        //if (DebugLevel>=3)
            qDebug()<<"WARNING::DBG.L3::"<<DBGPlace<<":[0089]::"<<Msg;
      };

    Line1=Line1.trimmed();
    if (Line1.startsWith("#")) Line1=Line1.mid(1);//отсечем комментарий
    if (Line1.endsWith(";")) Line1.chop(1);//отсечем окончание комментария

    QStringList ScriptOptionList=Line1.split(";");// пока будем считать что в строке одна опция
    QStringList VarValue=ScriptOptionList.at(0).split("=");//пока анализируем первый
    if (VarValue.at(0).toLower()==QDroidCodePageOption.toLower())
        CurrentScriptCodePage=VarValue.at(1);

    QString DefaultCodePage="Windows-1251";
    if (CurrentScriptCodePage.trimmed().isEmpty())
     {
        QString Msg="[WARNING] Codepage load-directive does not included. Using Default codepage: ["+DefaultCodePage+"]";
        //emit std_out("WARNING::"+DBGPlace+":[0108]"+Msg);
        //if (DebugLevel>=2)
            qDebug()<<"WARNING:DBG.L2::"<<DBGPlace<<":[0108]::"<<Msg;
        CurrentScriptCodePage=DefaultCodePage;//emit std_out("[NOTE!] t_FunctionRegistryItem::loadNewScript()::[0077]: codepage ["+CurrentScriptCodePage+"]does not supported yet.");
     };

    QTextCodec *Codec = QTextCodec::codecForName(CurrentScriptCodePage.toAscii());
    if (Codec==NULL)
     {
        QString Msg="[WARNING] Codepage ["+CurrentScriptCodePage+"] specify in script-file does not supported. Using Default codepage: ["+DefaultCodePage+"]";
        //emit std_out(DBGPlace+":[0116]"+Msg);
        //if (DebugLevel>=2)
          qDebug()<<"WARNING:: DBG.L2::"<<DBGPlace<<":[0117]::"<<Msg;
        Codec = QTextCodec::codecForName(DefaultCodePage.toAscii()); //
     };

    QByteArray line;
    //и загрузим оставшуюся часть скрипта с конвертацией кодировки в UTF-8
    file.reset();
    while (!file.atEnd())
                {
                        line = file.readLine();
                        if (DebugLevel>=5) qDebug()<<"DBG.L3::"<<DBGPlace<<":[0112]:: ScriptDump:"<<line;
                        ScriptSource.append(QString().append(Codec->toUnicode(line)));
                };
    Msg="[OK] script loaded from file: ["+_FileName+"]";
    //emit std_out(DBGPlace+":[0125]"+Msg);
    if (DebugLevel>=3) qDebug()<<"DBG.L3::"<<DBGPlace<<":[0125]::"<<Msg;

    return 0;
}

/*
supported codepages:
Apple Roman
Big5
Big5-HKSCS
EUC-JP
EUC-KR
GB18030-0
IBM 850
IBM 866
IBM 874
ISO 2022-JP
ISO 8859-1 to 10
ISO 8859-13 to 16
Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml
JIS X 0201
JIS X 0208
KOI8-R
KOI8-U
MuleLao-1
ROMAN8
Shift-JIS
TIS-620
TSCII
UTF-8
UTF-16
UTF-16BE
UTF-16LE
UTF-32
UTF-32BE
UTF-32LE
Windows-1250 to 1258
WINSAMI2
*/



//---------------------------------------------------------------------
//---------------------------------------------------------------------
//:: функции работы с исполняемыми скриптами не всегда загружаемыми из внешнего файла.
// скажем так - предварительный кеш.
//---------------------------------------------------------------------
QStringList t_QDroid::getLoadedScript()//++2010.06.24 вернуть имя скрипта
{
    return this->ScriptSource;
};

//---------------------------------------------------------------------
QScriptValue t_QDroid::runScript(QStringList _source, QObject* _context)//++2010.06.24 выполнить скрипт
{
    //надо установить _context как стандартную переменную в среде исполнения
 /*TODELETE*///   QScriptValue ScriptObjectValue_local1 = QSEngine->newQObject(_context);
 /*TODELETE*///   QSEngine->globalObject().setProperty(QDroid_StandartVar_LocalContext_Name, ScriptObjectValue_local1);

    return this->evaluateScript(_source,_context);
};

//---------------------------------------------------------------------
QScriptValue t_QDroid::runScript(QString _source, QObject* _context)//++2010.06.24 выполнить скрипт
{
    //надо установить _context как стандартную переенную в среде исполнения
/*TODELETE*/ //   QScriptValue ScriptObjectValue_local1 = QSEngine->newQObject(_context);
/*TODELETE*/ //   QSEngine->globalObject().setProperty(QDroid_StandartVar_LocalContext_Name, ScriptObjectValue_local1);
   // QStringList _source2(_source);

    return this->evaluateScript(QStringList(_source),_context);
}
// что делать с _context - скрипт сам должен разобраться. мы его погрузим в скрипт под
// под заданным именем а скрипт сам должен решить.



//---------------------------------------------------------------------
//++2010.07.06
QScriptValue t_QDroid::setScriptObjectVar(QString _name, QObject* _object)
{

    QScriptValue ScriptObjectValue_local1;
    if ( _object == 0 ) //дабы стереть объект)
        ScriptObjectValue_local1 = QScriptValue();
      else
        ScriptObjectValue_local1 = QSEngine->newQObject(_object);

    QSEngine->globalObject().setProperty(_name, ScriptObjectValue_local1);
    return ScriptObjectValue_local1;
}
//---------------------------------------------------------------------
//++2010.07.06
QScriptValue t_QDroid::setScriptVar(QString _name, QString _value)
{
    QScriptValue ScriptObjectValue_local1;
    if ( _value.isNull() ) //дабы стереть объект)
        ScriptObjectValue_local1 = QScriptValue();
      else
        ScriptObjectValue_local1 = QScriptValue(_value);

    QSEngine->globalObject().setProperty(_name, ScriptObjectValue_local1);
    return ScriptObjectValue_local1;
}

//---------------------------------------------------------------------
//++2011.02.22
QScriptValue t_QDroid::getScriptVar(QString _name)
{
    QScriptValue ScriptObjectValue_local1;

    ScriptObjectValue_local1=QSEngine->globalObject().property(_name);
    return ScriptObjectValue_local1;
}

//---------------------------------------------------------------------
